package fussbudget;

import fussbudget.PaymentEntity.Type;
import fussbudget.SQL.FBSQL;
import fussbudget.SQL.SQLUtility;
import interfaces.IcolumnData;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.EnumSet;

import org.joda.money.Money;
import org.joda.time.DateMidnight;

public class Transaction implements IcolumnData {
	public enum TYPE {
		DEPOSIT,
		PAYMENT
	}

	public enum DATE_MODE {
		DUE,
		EXPECTED,
		ACTUAL
	}

	public DATE_MODE		dateMode	= DATE_MODE.DUE;

	private int				id			= -1;
	private PaymentEntity	paymentEntity;
	private String			name		= "";
	SimpleTransaction		due			= new SimpleTransaction();
	SimpleTransaction		expected	= new SimpleTransaction();
	SimpleTransaction		actual		= new SimpleTransaction();
	private boolean			paid		= false;
	private TYPE			type;

	public Transaction(String name) {
		this.name = name;
		id = FBSQL.addTransaction(this);
	}

	public Transaction(ResultSet rs) {
		try {
			id = rs.getInt("id");
			name = rs.getString("name");
			paid = rs.getBoolean("paid");
			int dueID = rs.getInt("idDue");
			int expectedID = rs.getInt("idExpected");
			int actualID = rs.getInt("idActual");
			due = new SimpleTransaction(FBSQL.getResultSet("simpleTransaction", "*", "id=" + dueID));
			expected = new SimpleTransaction(FBSQL.getResultSet("simpleTransaction", "*", "id=" + expectedID));
			actual = new SimpleTransaction(FBSQL.getResultSet("simpleTransaction", "*", "id=" + actualID));

			int idPaymentEntity = rs.getInt("idPaymentEntity");
			
			if(rs.getBoolean("isDeposit")){
				type = TYPE.DEPOSIT;
				paymentEntity = FussBudgetMain.payerSet.getEntityByID(idPaymentEntity);
			}else{
				type = TYPE.PAYMENT;
				paymentEntity = FussBudgetMain.payeeSet.getEntityByID(idPaymentEntity);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public boolean isOverdue() {
		DateMidnight now = new DateMidnight();
		if (due.getDate().isAfter(now)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean hasBeenPaid() {
		return paid;
	}

	public void setPaid(boolean isPaid) {
		paid = isPaid;
		FBSQL.alterBoolean("transaction", "paid", isPaid, this.getId());
	}

	@Override
	public String toString() {
		return "Transaction [due=" + due + ", expected=" + expected + ", actual=" + actual + "]";
	}

	public synchronized PaymentEntity getPaymentEntity() {
		if (paymentEntity != null) {
			return paymentEntity;
		} else {
			return PaymentEntitySet.undefinedEntity;
		}
	}

	public synchronized void setPaymentEntity(PaymentEntity paymentEntity) {
		this.paymentEntity = paymentEntity;
		FBSQL.alterInt("transaction", "idPaymentEntity", paymentEntity.getId(), this.getId());
	}

	public synchronized DateMidnight getDate() {
		switch (dateMode) {
			case DUE:
				return due.getDate();
			case EXPECTED:
				return expected.getDate();
			case ACTUAL:
				return actual.getDate();
		}
		return null;
	}

	public synchronized Money getAmount() {
		switch (dateMode) {
			case DUE:
				return due.getAmount();
			case EXPECTED:
				return expected.getAmount();
			case ACTUAL:
				return actual.getAmount();
		}
		return null;
	}

	public synchronized void setDate(DateMidnight newDate) {
		switch (dateMode) {
			case DUE:
				due.setDate(newDate);
			case EXPECTED:
				expected.setDate(newDate);
			case ACTUAL:
				actual.setDate(newDate);
		}
	}

	public synchronized void setAmount(Money newMoney) {
		switch (dateMode) {
			case DUE:
				due.setAmount(newMoney);
			case EXPECTED:
				expected.setAmount(newMoney);
			case ACTUAL:
				actual.setAmount(newMoney);
		}
	}

	/**
	 * @return the id
	 */
	public synchronized int getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public synchronized void setId(int id) {
		this.id = id;
		FBSQL.alterInt("transaction", "id", id, this.getId());
	}

	/**
	 * @return the name
	 */
	public synchronized String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public synchronized void setName(String name) {
		this.name = name;
		FBSQL.alterString("transaction", "name", name, this.getId());
	}

	/**
	 * @return the due
	 */
	public synchronized SimpleTransaction getDue() {
		return due;
	}

	/**
	 * @param due
	 *            the due to set
	 */
	public synchronized void setDue(SimpleTransaction due) {
		this.due = due;
		FBSQL.alterInt("transaction", "idDue", due.getId(), this.getId());
	}

	/**
	 * @return the expected
	 */
	public synchronized SimpleTransaction getExpected() {
		return expected;
	}

	/**
	 * @param expected
	 *            the expected to set
	 */
	public synchronized void setExpected(SimpleTransaction expected) {
		this.expected = expected;
		FBSQL.alterInt("transaction", "idExpected", expected.getId(), this.getId());
	}

	/**
	 * @return the actual
	 */
	public synchronized SimpleTransaction getActual() {
		return actual;
	}

	/**
	 * @param actual
	 *            the actual to set
	 */
	public synchronized void setActual(SimpleTransaction actual) {
		this.actual = actual;
		FBSQL.alterInt("transaction", "idActual", actual.getId(), this.getId());
	}

	public synchronized TYPE getType() {
		return type;
	}

	public synchronized void setType(TYPE type) {
		this.type = type;
	}

	public synchronized boolean isPaid() {
		return paid;
	}

	public Object getElement(String colName) {
		if (colName.equals("NAME")) {
			return getName();
		} else if (colName.equals("DATE")) {
			return getDate();
		} else if (colName.equals("DUE DATE")) {
			return getDate();
		} else if (colName.equals("EXPECTED DATE")) {
			return getDate();
		} else if (colName.equals("ACTUAL DATE")) {
			return getDate();
		} else if (colName.equals("AMOUNT")) {
			return getAmount();
		} else if (colName.equals("WHO...")) {
			return getPaymentEntity();
		}
		return null;
	}

	public void setElement(String colName, Object value) {
		if (colName.equals("NAME")) {
			setName((String) value);
		} else if (colName.equals("DATE")) {
			setDate((DateMidnight) value);
		} else if (colName.equals("DUE DATE")) {
			setDate((DateMidnight) value);
		} else if (colName.equals("EXPECTED DATE")) {
			setDate((DateMidnight) value);
		} else if (colName.equals("ACTUAL DATE")) {
			setDate((DateMidnight) value);
		} else if (colName.equals("AMOUNT")) {
			setAmount((Money) value);
		} else if (colName.equals("WHO...")) {
			setPaymentEntity((PaymentEntity) value);
		}
	}
}
